package com.zcs.lib.sketchpad.view

import android.content.Context
import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.Path
import android.graphics.Point
import android.util.AttributeSet
import android.util.Log
import android.view.MotionEvent
import android.view.View
import com.zcs.lib.sketchpad.bean.EventPoint
import com.zcs.lib.sketchpad.config.SketchConfig
import kotlin.math.abs

/**
 * Created by ZengCS on 2021/11/30.
 * E-mail:zengcs@vip.qq.com
 * Add:成都市天府软件园E3-3F
 */
class BezierSketchView @JvmOverloads constructor(
    context: Context?,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) :
    View(context, attrs, defStyleAttr) {

    private var mLastEventX = 0f
    private var mLastEventY = 0f
    private var mBezierPaint = Paint()
    private val mBezierPath = Path()

    private val mEventList = ArrayList<EventPoint>()

    override fun onTouchEvent(event: MotionEvent): Boolean {
        if (event.action == MotionEvent.ACTION_DOWN) {
            // 添加一个EventPoint
            mEventList.add(EventPoint())
        }
        // 添加一个点
        mEventList.last().eventPointList.add(Point(event.x.toInt(), event.y.toInt()))
        // 事件处理
        when (event.action) {
            MotionEvent.ACTION_DOWN -> onFingerDown(event)
            MotionEvent.ACTION_MOVE -> onFingerMove(event)
            MotionEvent.ACTION_UP -> onFingerUp(event)
        }
        //更新绘制
        invalidate()
        return true
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        // 通过画布绘制多点形成的图形
        canvas.drawPath(mBezierPath, mBezierPaint)
    }

    // 手指点下屏幕时调用
    private fun onFingerDown(event: MotionEvent) {
        // 重置绘制路线，即隐藏之前绘制的轨迹
        // mBezierPath.reset()
        mLastEventX = event.x
        mLastEventY = event.y
        // mPath绘制的绘制起点
        mBezierPath.moveTo(mLastEventX, mLastEventY)
    }

    /**
     * 手指离开屏幕了
     * 1.缓存本次动作所有的点
     */
    private fun onFingerUp(event: MotionEvent) {
        Log.d("TAG/D", "eventPointList.size = ${mEventList.last().eventPointList.size}")
        Log.d("TAG/D", "     eventPointList = ${mEventList.last().eventPointList}")
    }

    // 手指在屏幕上滑动时调用
    private fun onFingerMove(event: MotionEvent) {
        val eventX = event.x
        val eventY = event.y
        val previousX = mLastEventX
        val previousY = mLastEventY

        // 计算本次滑动距离
        val dx = abs(eventX - previousX)
        val dy = abs(eventY - previousY)

        // 两点之间的距离大于等于3时，生成贝塞尔绘制曲线
        if (dx >= 3 || dy >= 3) {
            // 设置贝塞尔曲线的操作点为起点和终点的一半
            val controlX = (eventX + previousX) / 2
            val controlY = (eventY + previousY) / 2

            // 二次贝塞尔，实现平滑曲线；previousX, previousY为操作点，controlX, controlY为终点
            mBezierPath.quadTo(previousX, previousY, controlX, controlY)

            // 第二次执行时，第一次结束调用的坐标值将作为第二次调用的初始坐标值
            mLastEventX = eventX
            mLastEventY = eventY
        }
    }

    init {
        // 设置画笔颜色
        mBezierPaint.color = SketchConfig.currColor
        // 设置画笔宽度(单位px)
        mBezierPaint.strokeWidth = SketchConfig.getCurrLineWidth(context).toFloat()
        // 设置画笔样式
        mBezierPaint.style = Paint.Style.STROKE
        // 画笔开始和结束为圆
        mBezierPaint.strokeCap = Paint.Cap.ROUND
        // 连接处为圆
        mBezierPaint.strokeJoin = Paint.Join.ROUND
        // 当style为STROKE或FILL_AND_STROKE时设置连接处的倾斜度，这个值必须大于0
        mBezierPaint.strokeMiter = 1.0f
        // 设置画笔透明度
        mBezierPaint.alpha = 0xFF
        // 设置抗锯齿
        mBezierPaint.isAntiAlias = true
    }
}